/* hal_clock.c */

#include "hal_clock.h"

void CLOCK_EnablePeriph(uint32_t periph_id, bool enable)
{
    uint32_t group = CLOCK_GET_PERIPH_GROUP(periph_id);
    uint32_t subid = CLOCK_GET_PERIPH_SUBID(periph_id);
    
    switch (group)
    {
        case 0u:
            if (enable)
            {
                GCR->PCLKDIS0 &= ~(1u << subid);
            }
            else
            {
                GCR->PCLKDIS0 |= (1u << subid);
            }
            break;
       
        case 1u:
            if (enable)
            {
                GCR->PCLKDIS1 &= ~(1u << subid);
            }
            else
            {
                GCR->PCLKDIS1 |= (1u << subid);
            }
            break;
            
        case 2u:
            if (enable)
            {
                LPGCR->PCLKDIS &= ~(1u << subid);
            }
            else
            {
                LPGCR->PCLKDIS |= (1u << subid);
            }
            break;

        default:
            break;
    }
}

void CLOCK_ResetPeriph(uint32_t reset_id)
{
    uint32_t group = CLOCK_GET_PERIPH_GROUP(reset_id);
    uint32_t subid = CLOCK_GET_PERIPH_SUBID(reset_id);
    
    switch (group)
    {
        case 0u: /* GCR->RST0. */
            GCR->RST0 = (1u << subid);
            while (0u != (GCR->RST0 & (1u <<subid)))
            {}
            break;
        
        case 1u: /* GCR->RST1. */
            GCR->RST1 = (1u << subid);
            while (0u != (GCR->RST1 & (1u <<subid)))
            {}
            break;
        
        case 2u: /* LPGCR->RST. */
            LPGCR->RST = (1u << subid);
            while (0u != (LPGCR->RST & (1u <<subid)))
            {}
            break;
       
        default:
            break;
    }
}


void CLOCK_SetSysclkSel(CLOCK_ClkSrc_Type src, uint32_t div)
{
    GCR->CLKCTRL = (GCR->CLKCTRL & ~(GCR_CLKCTRL_SYSCLK_SEL_MASK | GCR_CLKCTRL_SYSCLK_DIV_MASK)) 
                 | (src << GCR_CLKCTRL_SYSCLK_SEL_SHIFT)
                 | (div << GCR_CLKCTRL_SYSCLK_DIV_SHIFT)
                 ;
    /* wait until the new selection ready. */
    while (0u == (GCR->CLKCTRL & GCR_CLKCTRL_SYSCLK_RDY_MASK))
    {}
}

void CLOCK_EnableClkSrc(CLOCK_ClkSrc_Type src)
{
    switch (src)
    {
        case CLOCK_ClkSrc_ISO   :
            GCR->CLKCTRL |= GCR_CLKCTRL_ISO_EN_MASK;
            while (0u == (GCR->CLKCTRL & GCR_CLKCTRL_ISO_RDY_MASK))
            {}
            break;

        case CLOCK_ClkSrc_IPO   :
            GCR->CLKCTRL |= GCR_CLKCTRL_IPO_EN_MASK;
            while (0u == (GCR->CLKCTRL & GCR_CLKCTRL_IPO_RDY_MASK))
            {}
            break;

        case CLOCK_ClkSrc_IBRO  :
            GCR->CLKCTRL |= GCR_CLKCTRL_IBRO_EN_MASK;
            while (0u == (GCR->CLKCTRL & GCR_CLKCTRL_IBRO_RDY_MASK))
            {}
            break;

        case CLOCK_ClkSrc_ERTCO :
            GCR->CLKCTRL |= GCR_CLKCTRL_ERTCO_EN_MASK;
            while (0u == (GCR->CLKCTRL & GCR_CLKCTRL_ERTCO_RDY_MASK))
            {}
            break;

        default:
            break;
    }
}

void CLOCK_DisableClkSrc(CLOCK_ClkSrc_Type src)
{
    switch (src)
    {
        case CLOCK_ClkSrc_ISO   :
            GCR->CLKCTRL &= ~GCR_CLKCTRL_ISO_EN_MASK;
            break;

        case CLOCK_ClkSrc_IPO   :
            GCR->CLKCTRL &= ~GCR_CLKCTRL_IPO_EN_MASK;
            break;

        case CLOCK_ClkSrc_IBRO  :
            GCR->CLKCTRL &= ~GCR_CLKCTRL_IBRO_EN_MASK;
            break;

        case CLOCK_ClkSrc_ERTCO :
            GCR->CLKCTRL &= ~GCR_CLKCTRL_ERTCO_EN_MASK;
            break;

        default:
            break;
    }
}

#if 0
extern uint32_t SystemCoreClock;
volatile bool SysTick_Timeout;

void CLOCK_DelayUs(uint32_t us)
{
    SysTick_Timeout = false;
    SysTick_Config(SystemCoreClock / 1000000u * us);
    while ( !SysTick_Timeout)
    {}
}

void CLOCK_DelayMs(uint32_t ms)
{
    SysTick_Timeout = false;
    SysTick_Config(SystemCoreClock / 1000u * ms);
    while ( !SysTick_Timeout)
    {}
}

void SysTick_Handler(void)
{
    /* disable the systick timer. */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    SysTick_Timeout = true;
}
#endif

/* EOF. */

